/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package Wires.impl;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.m2m.atl.engine.AtlEMFModelHandler;
import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModel;
import org.eclipse.m2m.atl.engine.vm.nativelib.ASMOclAny;

import Wires.DataType;
import Wires.FormalParameter;
import Wires.Model;
import Wires.ModelType;
import Wires.WiresPackage;
import Wires.exep.MetamodelNotFoundException;
import Wires.exep.ResourceNotFoundException;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Formal Parameter</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link Wires.impl.FormalParameterImpl#getTypeEl <em>Type El</em>}</li>
 *   <li>{@link Wires.impl.FormalParameterImpl#getTypeName <em>Type Name</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public abstract class FormalParameterImpl extends TypeImpl implements FormalParameter {
	/***************************************************/
	/***************** Modifications *******************/
	
	ASMModel model;
	ASMModel metamodel;
	ASMOclAny basicDataValue;
	String modelPath;
	
	public String getModelPath(){
		return modelPath;
	}
	
	public void setModelPath(String modelPath){
		this.modelPath = modelPath;
	}
	
	public ASMModel getModel(){
		return model;
	}
	
	public ASMModel getMetamodel(){
		return metamodel;
	}
	
	public ASMOclAny getBasicDataValue(){
		return this.basicDataValue;
	}
	
	public void setBasicDataValue(ASMOclAny newValue){
		this.basicDataValue = newValue;
	}
	
	public void loadMetamodel(){
//		String metamodelPath = this.getTypeEl().getPath();
//		URI metamodelResource = URI.createFileURI(metamodelPath);
//		String mmName = this.getTypeName();
//		AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
//		this.metamodel = modelHandler.loadModel(mmName, modelHandler.getMof(), metamodelResource);
		
		AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
		if (this.getTypeEl() == null){
			throw new MetamodelNotFoundException(this);
		}
		String metamodelPath = this.getTypeEl().getPath();
		// Load metamodel by file path
		if (this.getTypeEl().getPath() != null && !this.getTypeEl().getPath().equals("")){ 
			URI metamodelResource;
			try {
				metamodelResource = URI.createFileURI(metamodelPath);
			} catch (Exception e) {
				throw new ResourceNotFoundException(this.getTypeEl());
			}
			String mmName = this.getTypeName();		
			this.metamodel = modelHandler.loadModel(mmName, modelHandler.getMof(), metamodelResource);
		}else{
			metamodelPath = ((ModelType)this.getTypeEl()).getUri();		
			// Load metamodel by URI
			if (metamodelPath != null && !metamodelPath.trim().equals("")){
				String mmName = this.getTypeName();			
				this.metamodel = modelHandler.loadModel(mmName, modelHandler.getMof(), "uri:" + metamodelPath);				
			}else{
				// Find model which name equals to the metamodel name and the model found is the metamodel
				String metamodelName = this.getTypeEl().getName();
				
				EObject o = this;
				while (! (o instanceof WiresSpecificationImpl)){
					o = o.eContainer();
				}
				
				Model m = ((WiresSpecificationImpl)o).getModelByName(metamodelName);
				if (m == null)
					throw new MetamodelNotFoundException(this);
				String modelPath = m.getPath();
				URI modelResource = URI.createFileURI(modelPath);
				String modelName = m.getName();			
				this.metamodel = modelHandler.loadModel(modelName, modelHandler.getMof(), modelResource);				
			}
		}
	}
	
	/**************** Modifications End ****************/
	/***************************************************/
	
	/**
	 * The cached value of the '{@link #getTypeEl() <em>Type El</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getTypeEl()
	 * @generated
	 * @ordered
	 */
	protected DataType typeEl;

	/**
	 * The default value of the '{@link #getTypeName() <em>Type Name</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getTypeName()
	 * @generated
	 * @ordered
	 */
	protected static final String TYPE_NAME_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getTypeName() <em>Type Name</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getTypeName()
	 * @generated
	 * @ordered
	 */
	protected String typeName = TYPE_NAME_EDEFAULT;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected FormalParameterImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return WiresPackage.Literals.FORMAL_PARAMETER;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public DataType getTypeEl() {
		if (typeEl != null && typeEl.eIsProxy()) {
			InternalEObject oldTypeEl = (InternalEObject)typeEl;
			typeEl = (DataType)eResolveProxy(oldTypeEl);
			if (typeEl != oldTypeEl) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE, WiresPackage.FORMAL_PARAMETER__TYPE_EL, oldTypeEl, typeEl));
			}
		}
		return typeEl;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public DataType basicGetTypeEl() {
		return typeEl;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setTypeEl(DataType newTypeEl) {
		DataType oldTypeEl = typeEl;
		typeEl = newTypeEl;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, WiresPackage.FORMAL_PARAMETER__TYPE_EL, oldTypeEl, typeEl));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public String getTypeName() {
		return typeName;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setTypeName(String newTypeName) {
		String oldTypeName = typeName;
		typeName = newTypeName;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, WiresPackage.FORMAL_PARAMETER__TYPE_NAME, oldTypeName, typeName));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case WiresPackage.FORMAL_PARAMETER__TYPE_EL:
				if (resolve) return getTypeEl();
				return basicGetTypeEl();
			case WiresPackage.FORMAL_PARAMETER__TYPE_NAME:
				return getTypeName();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case WiresPackage.FORMAL_PARAMETER__TYPE_EL:
				setTypeEl((DataType)newValue);
				return;
			case WiresPackage.FORMAL_PARAMETER__TYPE_NAME:
				setTypeName((String)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case WiresPackage.FORMAL_PARAMETER__TYPE_EL:
				setTypeEl((DataType)null);
				return;
			case WiresPackage.FORMAL_PARAMETER__TYPE_NAME:
				setTypeName(TYPE_NAME_EDEFAULT);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case WiresPackage.FORMAL_PARAMETER__TYPE_EL:
				return typeEl != null;
			case WiresPackage.FORMAL_PARAMETER__TYPE_NAME:
				return TYPE_NAME_EDEFAULT == null ? typeName != null : !TYPE_NAME_EDEFAULT.equals(typeName);
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (typeName: ");
		result.append(typeName);
		result.append(')');
		return result.toString();
	}

} //FormalParameterImpl
